<template>
	<div class="sc-upload-file">
		<el-upload
			v-model:file-list="defaultFileList"
			:disabled="props.disabled"
			:auto-upload="props.autoUpload"
			:action="props.action"
			:name="props.name"
			:data="props.data"
			:http-request="request"
			:show-file-list="props.showFileList"
			:drag="props.drag"
			:accept="props.accept"
			:multiple="props.multiple"
			:limit="props.limit"
			:before-upload="before"
			:before-remove="beforeRemove"
			:on-success="success"
			:on-error="error"
			:on-preview="handlePreview"
			:on-exceed="handleExceed">
			<slot>
				<el-button type="primary" :disabled="props.disabled">Click to upload</el-button>
			</slot>
			<template #tip>
				<div v-if="tip" class="el-upload__tip">{{ tip }}</div>
			</template>
		</el-upload>
		<span style="display: none !important"><el-input v-model="value"></el-input></span>
	</div>
</template>
<script setup lang="ts">
	const emit = defineEmits(['update:modelValue'])
	const props = defineProps({
		modelValue: { type: [String, Array], default: '' },
		tip: { type: String, default: '' },
		action: { type: String, default: '' },
		apiObj: { type: Object, default: () => {} },
		name: { type: String, default: files.filename },
		data: { type: Object, default: () => {} },
		accept: { type: String, default: '' },
		maxSize: { type: Number, default: files.maxSizeFile },
		limit: { type: Number, default: 0 },
		autoUpload: { type: Boolean, default: true },
		showFileList: { type: Boolean, default: true },
		drag: { type: Boolean, default: false },
		multiple: { type: Boolean, default: true },
		disabled: { type: Boolean, default: false },
		onSuccess: { type: Function, default: () => true }
	})
	const value = ref<any>('')
	const defaultFileList = ref<any>([])
	watch(
		() => props.modelValue,
		(val) => {
			if (Array.isArray(val)) {
				if (JSON.stringify(val) != JSON.stringify(formatArr(defaultFileList.value))) {
					defaultFileList.value = val
					value.value = val
				}
			} else {
				if (val != toStr(defaultFileList.value)) {
					defaultFileList.value = toArr(val)
					value.value = val
				}
			}
		}
	)
	watch(
		() => defaultFileList.value,
		(val) => {
			emit('update:modelValue', Array.isArray(props.modelValue) ? formatArr(val) : toStr(val))
			value.value = toStr(val)
		},
		{ deep: true }
	)
	onMounted(() => {
		defaultFileList.value = Array.isArray(props.modelValue) ? props.modelValue : toArr(props.modelValue)
		value.value = props.modelValue
	})
	const toArr = (str: string) => {
		var _arr: { name: string; url: string }[] = []
		var arr = str.split(',')
		arr.forEach((item) => {
			if (item) {
				var urlArr = item.split('/')
				var fileName = urlArr[urlArr.length - 1]
				_arr.push({
					name: fileName,
					url: item
				})
			}
		})
		return _arr
	}
	const toStr = (arr: any[]) => arr.map((v) => v.url).join(',')
	const formatArr = (arr: any[]) => {
		var _arr: { name: any; url: any }[] = []
		arr.forEach((item) => {
			if (item) {
				_arr.push({
					name: item.name,
					url: item.url
				})
			}
		})
		return _arr
	}
	const before = (file: { size: number }) => {
		const maxSize = file.size / 1024 / 1024 < props.maxSize
		if (!maxSize) {
			ElMessage.warning(`上传文件大小不能超过 ${props.maxSize}MB!`)
			return false
		}
	}
	const success = (res: { code: number; data: { name: string; src: string }; message: string }, file: { name: string; url: string }) => {
		var os = props.onSuccess(res, file)
		if (os != undefined && os == false) {
			return false
		}
		var response = files.parseData(res)
		file.name = response.fileName
		file.url = response.src
	}
	const error = (err: any) => {
		ElNotification.error({
			title: '上传文件未成功',
			message: err
		})
	}
	const beforeRemove = async (uploadFile: { name: string }) => {
		try {
			await ElMessageBox.confirm(`是否移除 ${uploadFile.name} ?`, '提示', {
				type: 'warning'
			})
			return true
		} catch {
			return false
		}
	}
	const handleExceed = () => ElMessage.warning(`当前设置最多上传 ${props.limit} 个文件，请移除后上传!`)
	const handlePreview = (uploadFile: { url: any }) => window.open(uploadFile.url)
	const request = (param: any) => {
		var apiObj = props.apiObj ? props.apiObj : files.apiObjFile
		const data = new FormData()
		data.append(param.filename, param.file)
		for (const key in param.data) {
			data.append(key, param.data[key])
		}
		apiObj
			.post(data, {
				onUploadProgress: (e: { loaded: number; total: number }) => {
					const complete = parseInt((((e.loaded / e.total) * 100) | 0).toString(), 10)
					param.onProgress({ percent: complete })
				}
			})
			.then((res: any) => {
				var response = files.parseData(res)
				if (response.code == files.successCode) {
					param.onSuccess(res)
				} else {
					param.onError(response.msg || '未知错误')
				}
			})
			.catch((err: any) => {
				param.onError(err)
			})
	}
</script>
<style lang="less" scoped>
	.el-form-item.is-error .sc-upload-file:deep(.el-upload-dragger) {
		border-color: var(--el-color-danger);
	}
	.sc-upload-file {
		width: 100%;
	}
	.sc-upload-file:deep(.el-upload-list__item) {
		transition: none !important;
	}
</style>
